package waitnotify;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class GuardedObject {
    private static final Object lock = new Object();
    private static Object result = null;

    public Object get(long totalWaitTime) throws InterruptedException {
        synchronized (lock) {
            // 获取锁对象的时刻
            long getLockTime = System.currentTimeMillis();
            // wait结束后 到 下次获取锁的时间差  wait结束可能是被叫醒的 也可能是自醒
            long waitToNextGetLockPassTime = 0;

            while (result == null) {
                // 本来超时为5000的 但是在3000就被提前叫醒 则还需要wait 2000
                long shouldWaitTime = totalWaitTime - waitToNextGetLockPassTime;

                // 如果超时为5000 但是发现超过5000还没被notify 则直接判定超时 不需要再wait
                if (shouldWaitTime <= 0) {
                    log.info("线程wait自醒了还没有被叫醒，直接返回。。。");
                    break;
                }

                log.info("需要wait {}。。。", shouldWaitTime);
                lock.wait(shouldWaitTime);

                waitToNextGetLockPassTime = System.currentTimeMillis() - getLockTime;
                log.info("{}后被唤醒。。。", waitToNextGetLockPassTime);
            }
            return result;
        }
    }
    public void set(Object obj) throws InterruptedException {
        synchronized (lock) {
            lock.notifyAll();
            result = obj;
        }
    }

    public static void main(String[] args) throws InterruptedException {
        GuardedObject guardedObject = new GuardedObject();
        Thread t1 = new Thread(() -> {
            try {
                log.info("t1线程获得结果 => {}", guardedObject.get(5000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "t1");
        t1.start();
        Thread.sleep(6000);
        guardedObject.set(new Object());
    }
}
